﻿using System;
using System.Web.Mvc;
using System.Web.Routing;


namespace nanoCMS.Core.WebProviders.HtmlHelpers.Pagination {
	
	class PagerBuilder
	{
		private readonly PagerOptions _pagerOptions;
		private readonly RouteValueDictionary _routeValues;
		private readonly int _pageIndex;
		private readonly int _totalPageCount;
		private readonly HtmlHelper _htmlHelper;
		

		internal PagerBuilder(HtmlHelper htmlHelper, int pageIndex, int totalPageCount, PagerOptions pagerOptions, RouteValueDictionary routeValues)
		{
			_htmlHelper = htmlHelper;
			_pageIndex = pageIndex;
			_totalPageCount = totalPageCount;
			_pagerOptions = pagerOptions;
			_routeValues = routeValues;
		}

		private string GenerateUrl(int pageIndex)
		{
			//return null if  page index larger than total page count or page index is current page index
			if (pageIndex > _totalPageCount || pageIndex == _pageIndex)
				return null;

			// set route value of page index parameter name in url,pageIndex==0 is a special case
			if (_routeValues.ContainsKey(_pagerOptions.PageIndexParameterName))
			{
				_routeValues.Remove(_pagerOptions.PageIndexParameterName);
			}

			
			_routeValues.Add(_pagerOptions.PageIndexParameterName, pageIndex);
			

			string link = String.Empty;
			if (_htmlHelper.ViewContext.RequestContext.RouteData.Values["link"] != null)
				link = _htmlHelper.ViewContext.RequestContext.RouteData.Values["link"].ToString();


			return LinkHelper.CustomUrl(_htmlHelper.ViewContext.RequestContext, link, new RouteValueDictionary(_routeValues));


		}

		private TagBuilder RenderListItem(string text, int pageIndex, bool isDisabled = false)
		{
			TagBuilder listItem = new TagBuilder("li");
			listItem.MergeAttributes(_pagerOptions.ListHtmlAttributes);
			if (isDisabled)
			{
				TagBuilder link = new TagBuilder("a");
				link.MergeAttributes(_pagerOptions.LinkHtmlAttributes);
				link.AddCssClass(_pagerOptions.CurrentClass);
				link.MergeAttribute("disabled", "disabled");
				link.MergeAttribute("href", "#");
				link.SetInnerText(text);
				listItem.InnerHtml = link.ToString();
			}else
			{
				TagBuilder link = new TagBuilder("a");
				link.MergeAttributes(_pagerOptions.LinkHtmlAttributes);
				link.MergeAttribute("href", GenerateUrl(pageIndex));
				link.SetInnerText(text);
				listItem.InnerHtml = link.ToString();
			}
			return listItem;
		}

		private TagBuilder RenderList()
		{
			TagBuilder tagBuilder = new TagBuilder("ul");
			tagBuilder.MergeAttributes(_pagerOptions.ListHtmlAttributes);
			return tagBuilder;
		}


		private string RenderLinks()
		{
			string pagerLinks = String.Empty;
			if (_pagerOptions.ShowFirstLast)
				pagerLinks += RenderListItem(_pagerOptions.FirstText, 1, _pageIndex == 1);
			if (_pagerOptions.ShowPrevNext)
				pagerLinks += RenderListItem(_pagerOptions.PrevText, _pageIndex - 1, _pageIndex == 1);

			for(int i = 1; i <= _totalPageCount; i++)
			{
				pagerLinks += RenderListItem(i.ToString(), i, i == _pageIndex);
			}

			if (_pagerOptions.ShowPrevNext)
			{
				pagerLinks += RenderListItem(_pagerOptions.NextText, _pageIndex + 1, _pageIndex == _totalPageCount);
			}
			if (_pagerOptions.ShowFirstLast)
				pagerLinks += RenderListItem(_pagerOptions.LastText, _totalPageCount, _pageIndex == _totalPageCount);

			return pagerLinks;
		}


		private TagBuilder RenderContainter()
		{
			TagBuilder tagBuilder  = new TagBuilder(_pagerOptions.PagerContainerTag);
			tagBuilder.MergeAttributes(_pagerOptions.ContainterHtmlAttributes);
			return tagBuilder;
		}

		internal string Render()
		{
			TagBuilder container = RenderContainter();
			TagBuilder list = RenderList();
			list.InnerHtml = RenderLinks();

			container.InnerHtml = list.ToString();

			return container.ToString();
		}
	}


	public static class PagerHelper {


		public static MvcHtmlString Pager(this HtmlHelper htmlHelper, int totalItemCount, int pageSize, 
			int pageIndex, PagerOptions pagerOptions,object routeValues)
		{
			var totalPageCount = (int)Math.Ceiling(totalItemCount / (double)pageSize);
			if (totalPageCount <= 1 && pagerOptions.AutoHide) return MvcHtmlString.Empty;
			
			PagerBuilder pagerBuilder = new PagerBuilder(htmlHelper, pageIndex, totalPageCount, pagerOptions, new RouteValueDictionary( routeValues));
			return MvcHtmlString.Create(pagerBuilder.Render());
		}
	}
}
